/*
 * ===========================================================================
 *
 *      Filename: queue.c
 *   Description: implement queue with dl_list
 *        Author: Ye wenhao, wenhaoye@126.com
 *  Organization: 
 *
 * ===========================================================================
 */
#include "queue.h"
#include "def.h"

struct queue
{
    struct dl_list q_head;
    uint32_t nums;
    locker_t *locker;
};

queue_t *queue_create(locker_t *locker)
{
    queue_t *self = (queue_t *)MALLOC(sizeof(queue_t));
    if(self){
        self->locker = locker;
        dl_list_init(&self->q_head);
        self->nums = 0;
    }

    return self;
}

void queue_destroy(queue_t **p_self, dl_list_item_destroy_func destroy)
{
    if(p_self && *p_self){
        queue_t *self = *p_self;

        if(destroy){
            struct dl_list *item, *n;
            locker_lock(self->locker);
            dl_list_for_each_safe(item, n, &self->q_head){
                dl_list_del(item);
                (*destroy)(item);
                self->nums--;
            }
            locker_unlock(self->locker);
        }

        locker_destroy(self->locker);
        safe_free(self);
    }
}

int queue_in(queue_t *self, struct dl_list *item)
{
    if(self == NULL || item == NULL)
        return -1;

    locker_lock(self->locker);
    dl_list_add_tail(&self->q_head, item);
    self->nums++;
    locker_unlock(self->locker);

    return 0;
}

struct dl_list *queue_out(queue_t *self)
{
    if(self == NULL)
        return NULL;

    struct dl_list *item = NULL;
    locker_lock(self->locker);
    item = self->q_head.next;
    dl_list_del(item);
    self->nums--;
    locker_unlock(self->locker);

    return item;
}

uint32_t queue_item_nums(queue_t *self)
{
    if(self == NULL)
        return 0;

    return self->nums;
}
